﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;


namespace LinnCorLib.Net
{
    public class ChatClient
    {
        private Socket client = null;
        private byte[] byteReceiveMessage = new byte[1024];
        
        public bool Connected { get; private set; }

        public event EventHandler<ReceiveMessageEventArgs> ReceiveMessageEvent;


        public ChatClient() 
        {
            Connected = false;
            client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
        }

        public void ConnectServer(string ip, int port)
        {
            IPAddress ipServer = IPAddress.Parse(ip);

            try
            {
                client.Connect(new IPEndPoint(ipServer, port));
                Connected = true;

                client.BeginReceive(byteReceiveMessage, 0, byteReceiveMessage.Length, SocketFlags.None, new AsyncCallback(CallBack_ReceiveMessage), byteReceiveMessage);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Connected = false;
            }
        }

        public void SendMessage(string message)
        {
            byte[] byteSendMessage = new byte[1024];
            byteSendMessage = Encoding.Default.GetBytes(message);

            client.BeginSend(byteSendMessage, 0, byteSendMessage.Length, SocketFlags.None, new AsyncCallback(CallBack_SendMessage), byteSendMessage);
        }

        private void CallBack_SendMessage(IAsyncResult asyncResult)
        {
            byte[] bytes = (byte[])asyncResult.AsyncState;
            try
            {
                int send = client.EndSend(asyncResult);

                if (send == 0)
                {
                    Disconnect();
                    return;
                }

                //Console.WriteLine("Send - {0}bytes", send);

                client.BeginReceive(byteReceiveMessage, 0, byteReceiveMessage.Length, SocketFlags.None, new AsyncCallback(CallBack_ReceiveMessage), byteReceiveMessage);
            }
            catch (Exception ex)
            {
                Console.WriteLine("전송중 오류 - {0}", ex.Message);
                Disconnect();
            }
        }

        private void CallBack_ReceiveMessage(IAsyncResult asyncResult)
        {
            byte[] bytes = (byte[])asyncResult.AsyncState;
            try
            {
                int receiveSize = client.EndReceive(asyncResult);
                string receiveMessage = Encoding.Default.GetString(bytes, 0, receiveSize);
                //Console.WriteLine("Receive - {0}", receiveMessage);
                if (ReceiveMessageEvent != null)
                    ReceiveMessageEvent(this, new ReceiveMessageEventArgs(receiveMessage));

                client.BeginReceive(byteReceiveMessage, 0, byteReceiveMessage.Length, SocketFlags.None, new AsyncCallback(CallBack_ReceiveMessage), byteReceiveMessage);
            }
            catch (Exception ex)
            {
                Console.WriteLine("수신중 오류 - {0}", ex.Message);
                Disconnect();
            }
        }

        public void Disconnect()
        {
            if (client != null)
            {
                client.Close();
                client = null;
                Connected = false;
            }
        }
    }

    public class ReceiveMessageEventArgs : EventArgs
    {
        public string message { get; private set; }

        public ReceiveMessageEventArgs(string message)
        {
            this.message = message;
        }
    }
}
